package com.designoutput.utils {
	import com.designoutput.utils.fontExtractor.CFFFontInfo;
	
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	import org.purepdf.elements.ReadOnlyRectangle;

	public class FontExtractor {
		private static const UNCOMPRESSED_SIGNATURE:String = "FWS";
		private static const COMPRESSED_SIGNATURE:String = "CWS";
			
		public static function extractCFFFonts(data:ByteArray):Vector.<CFFFontInfo> {
			var fonts:Vector.<CFFFontInfo> = new Vector.<CFFFontInfo>();
						
			data.endian = Endian.LITTLE_ENDIAN;
			data.position = 0;
			
			if (data.bytesAvailable > 26) {
				var signature:String = data.readUTFBytes(3);
				
				if (signature != UNCOMPRESSED_SIGNATURE && signature != COMPRESSED_SIGNATURE)
					throw new ArgumentError('Error #2124: Loaded file is an unknown type.');
									
				if (signature == COMPRESSED_SIGNATURE)
						data = uncompress(data);
				
				data.position = 0;
				signature = data.readUTFBytes(3); //Read signature
				var version:int = data.readUnsignedByte(); //Read version
				var fileLength:uint = data.readUnsignedInt(); //Read file length
				skipRect(data);
				var frameRate:int = data.readUnsignedShort(); //Read frame rate
				var frameCount:int = data.readUnsignedShort(); //Read frame count
			} else {
				throw new ArgumentError('Insufficient data.');
			}
			
			while (data.bytesAvailable) {
				var tagHeader:uint = data.readUnsignedShort();
				var tagId:uint = tagHeader >> 6;
				var tagLength:uint = ((tagHeader & 0x3F) == 0x3F) ? data.readUnsignedInt() : (tagHeader & 0x3F);
				var tagStart:uint = data.position;
				
				switch (tagId) {
					case 91:
						var fontId:uint = data.readUnsignedShort(); //Font Id
												
						var bits:int = data.readUnsignedByte(); //Next 8 bits
						
						var cffFont:CFFFontInfo = new CFFFontInfo();
						var embedded:Boolean = (bits & 0x4) == 0x4;
						if(!embedded)
							break;

						cffFont.italic = (bits & 0x2) == 0x2;
						cffFont.bold = (bits & 0x1) == 0x1;						
						
						cffFont.fontName = readString(data);
						
						cffFont.fontData = new ByteArray();
						cffFont.fontData.writeBytes(data, data.position, tagLength - (data.position - tagStart));
						
						fonts.push(cffFont);
						break;
				}
				
				data.position = tagStart + tagLength;
			}
			
			return fonts;
		}
		
		private static function uncompress(data:ByteArray):ByteArray {
			var uncompressed:ByteArray = new ByteArray();
			data.position = 0;
			data.readBytes(uncompressed);
			uncompressed.uncompress();
			return uncompressed;
		}
		
		private static function skipRect(data:ByteArray):void {
			var bits:int = data.readByte() >> 3;
			data.position += Math.ceil(((bits * 4) - 3)/8);
		}
		
		private static function readString(data:ByteArray):String {
			var start:uint = data.position;
			var length:uint = 0;
			while(data.readByte() != 0)
				length++;
			data.position = start;
			var str:String = data.readUTFBytes(length);
			data.readByte();
			return str;
		}
	}
}